<?php

namespace App\Model;

use Hyperf\Database\Model\Model;
use Hyperf\DbConnection\Db;

/**
 * 用户行为日志
 */
class UserActLog extends Model
{
    protected $table = 'user_act_log';
    protected $fillable = [
        'user_id', 'act', 'flag', 'detail'
    ];

    //正常
    const FLAG_OK = 1;
    //不可操作
    const FLAG_NO = 0;
    //违规
    const FLAG_BAD = -1;
    //审核中
    const FLAG_ING = 2;

    //上线
    const ACT_ONLINE = 1;
    //离线
    const ACT_OFFLINE = 0;
    //提交头像
    const ACT_AVATAR = 2;
    //打开充值面板
    const ACT_RECHARGE_OPEN = 3;

    public function userProfile()
    {
        return $this->belongsTo(UserProfile::class, 'user_id', 'user_id');
    }

    /**
     * 添加
     */
    static function addRecord(
        $userId = 0,
        $act = self::ACT_ONLINE,
        $detail = '',
        $status = self::FLAG_OK
    ) {
        //运行
        if (self::ACT_AVATAR == $act) {
            $where = ['user_id' => $userId, 'act' => self::ACT_AVATAR];
            $last = self::where($where)->orderBy('id', 'desc')->first();
            if ($last && $last->detail == $detail) return false;
            $where['flag'] = self::FLAG_OK;
            self::where($where)->update(['flag' => self::FLAG_NO]);
        }
        return self::create([
            'user_id' => $userId,
            'act' => $act,
            'detail' => $detail,
            'flag' => $status
        ]);
    }

    /**
     * 最新上传的头像
     */
    static function getLastAvatar($userId = 0, $dataType = 'item')
    {
        $where = ['user_id' => $userId, 'act' => self::ACT_AVATAR];
        $item = self::where($where)->orderBy('id', 'desc')->first();
        if ($dataType == 'status') {
            return $item ? self::getStatus($item->flag) : 0;
        }
        return $item ?: null;
    }

    /**
     * 状态
     */
    static function getStatus($flag = 0)
    {
        switch ($flag) {
            case self::FLAG_OK:
                return 0;
            case self::FLAG_ING:
                return 1;
            case self::FLAG_NO:
            case self::FLAG_BAD:
                return 2;
        }
    }

    /**
     * 计算数组内多少
     */
    static function checkActiveCount($userIds = [], $startTime = '', $endTime = '', $channel = '', $type = 'count')
    {
        $where = [];
        if ($startTime) $where[] = ['user_act_log.created_at', '>=', $startTime];
        if ($endTime) $where[] = ['user_act_log.created_at', '<', $endTime];

        //指定注册渠道
        if (!$channel) {
            $query = self::where($where);
        } else {
            $query = Db::table('user_act_log')->join('user', function ($join) use ($channel, $where) {
                $where[] = ['channel', $channel];
                $join->on('user_act_log.user_id', '=', 'user.id')->where($where);
            });
        }

        //指定用户集
        if ($userIds) {
            $query = $query->whereIn('user_id', $userIds);
        }

        if ($type == 'uid') {
            $data = $query->select(Db::raw('distinct user_id'))->get()->toArray();
            return array_column($data, 'user_id');
        } else {
            $data = $query->select(Db::raw('count(distinct user_id) as ctn'))->first();
            return $data && $data->ctn ? $data->ctn : 0;
        }
    }

    /**
     * 获取最近一次登录
     */
    static function getLastOnlineTime($userId = 0, $startTime = '', $endTime = '')
    {
        $where = [
            ['user_id', $userId],
            ['act', self::ACT_ONLINE],
        ];
        if ($startTime) $where[] = ['created_at', '>=', $startTime];
        if ($endTime) $where[] = ['created_at', '<', $endTime];
        $data = self::where($where)->orderBy('id', 'desc')->first();
        return $data ? (string)$data->created_at : null;
    }

    /**
     * 男性活跃用户
     */
    static function checkCount($gender = -1, $role = -1, $startTime = '', $endTime = '', $channel = '')
    {
        $where = [];
        $data = 0;
        if ($startTime) $where[] = ['user_act_log.created_at', '>=', $startTime];
        if ($endTime) $where[] = ['user_act_log.created_at', '<', $endTime];

        if ($gender > -1) {
            $query = Db::table('user_profile')->join('user_act_log', function ($join) use ($gender, $where) {
                $where[] = ['user_profile.gender', $gender];
                $join->on('user_act_log.user_id', '=', 'user_profile.user_id')->where($where);
            });
        } elseif ($role > -1) {
            $query = Db::table('user_act_log')->join('user_profile', function ($join) use ($role, $where) {
                $where[] = ['user_profile.role', $role];
                $join->on('user_act_log.user_id', '=', 'user_profile.user_id')->where($where);
            });
        } else {
            $query = self::where($where);
        }

        //指定注册渠道
        if ($channel) {
            $query = $query->join('user', function ($join) use ($channel, $where) {
                $where[] = ['channel', $channel];
                $join->on('user_act_log.user_id', '=', 'user.id')->where($where);
            });
        }

        $data = $query->select(Db::raw('count(distinct t_user_act_log.user_id) as ctn'))->first();
        return $data && $data->ctn ? $data->ctn : 0;
    }

    /**
     * 用户在线时间（指定时间段）
     */
    static function onlineDuration($userId = 0, $start = '', $end = '')
    {
        if (!$userId) return [];
        $where = [];
        $start && $where[] = ['created_at', '>=', $start];
        $end && $where[] = ['created_at', '<', $end];
        $field = ['user_id', 'created_at', 'act'];
        if (is_array($userId)) {
            $data = self::where($where)->whereIn('user_id', $userId)->whereIn('act', [1, 0])->select($field)->orderBy('id', 'asc')->get()->toArray();
        } else {
            $where[] = ['user_id', $userId];
            $data = self::where($where)->whereIn('act', [1, 0])->select($field)->orderBy('id', 'asc')->get()->toArray();
        }
        $onlineInfo = $onlineStatus = [];
        $startTs = $start ? strtotime($start) : strtotime(date('Y-m-d'));
        foreach ($data as $item) {
            $userId = $item['user_id'];
            if (!isset($onlineInfo[$userId])) {
                $time = strtotime($item['created_at']) - $startTs;
                $onlineInfo[$userId] = $item['act'] == 1 ? 0 : ($time > 1200 ? 1200 : $time);
            } else {
                //上线-离线
                if ($onlineStatus[$userId]['act'] == 1 && $item['act'] == 0) {
                    $time = strtotime($item['created_at']) - strtotime($onlineStatus[$userId]['time']);
                    $onlineInfo[$userId] += $time > 1200 ? 1200 : $time;
                }
            }
            $onlineStatus[$userId] = [
                'act' => $item['act'],
                'time' => $item['created_at']
            ];
        }
        return $onlineInfo;
    }

    public static function onlineDurationV3($userId = 0, $start = '', $end = '')
    {
        if (!$userId) return [];
        $where = [];
        $start && $where[] = ['created_at', '>=', $start];
        $end && $where[] = ['created_at', '<', $end];
        $field = ['id','user_id', 'created_at', 'act'];
        if (!is_array($userId)) {
            $userId = [$userId];
        }

        $data = self::where($where)->whereIn('user_id', $userId)->whereIn('act', [1, 0])->select($field)->orderBy('id')->get()->toArray();

        $ClassifiedData = [];

        // 遍历原始数组，根据 'type' 列值归类产品信息
        foreach ($data as $item) {
            $type = $item['user_id'];

            // 如果当前类型尚未存在于归类数组中，则初始化一个空数组
            if (!isset($ClassifiedData[$type])) {
                $ClassifiedData[$type] = [];
            }

            $ClassifiedData[$type][] = $item;
        }

        $res = [];

        foreach ($ClassifiedData as$key => $one)
        {
//            $oneTime = array_column($one, 'created_at');
//            // 使用 array_multisort() 对数组按照年龄进行升序排序
//            array_multisort($oneTime, SORT_ASC, $one);

            $res[$key] = self::getDataSeconds($one,$start, $end);

        }

        return $res;
    }

    private static function getDataSeconds($data,$start,$end)
    {
        if (empty($data))
        {
            return 0;
        }

        $seconds = 0;
        $flag = 0;
        $loginTime = null;
        foreach ($data as $one)
        {
            $lastTime = next($data);
//            echo "\n";
            if ($one['act'] == 1) {
                if ($flag == 1)
                {
//                    echo $one['created_at'].'_===_'.$seconds.'==='."{$flag}|||{$loginTime}";
                    continue;
                }

                if ($flag == 0)
                {
                    $loginTime = $one['created_at'];
                    $flag = 1;
//                    echo $one['created_at'].'_===_'.$seconds.'==='."{$flag}|||{$loginTime}";
                    continue;
                }
            }

            if (!$lastTime && $flag == 1)
            {
                if (strtotime($end) - time() < 60) {
                    $seconds += strtotime($end) - strtotime($loginTime);
//                    echo $one['created_at'].'_===_'.$seconds.'==='."{$flag}|||{$loginTime}";
                    continue;
                }
            }

            if ($one['act'] == 0) {
//                echo '进来了';
                if ($flag == 0 && $loginTime == null && $lastTime['act'] == 0) {
//                    echo $one['created_at'].'_===_'.$seconds.'==='."{$flag}|||{$loginTime}";
                    continue;
                }

                if ($flag == 0 && $loginTime == null && $lastTime['act'] == 1) {
                    $seconds += strtotime($one['created_at']) - strtotime($start);
//                    echo $one['created_at'].'_===_'.$seconds.'==='."{$flag}|||{$loginTime}";
                    continue;
                }

                if ($flag == 1 && $loginTime == null) {
//                    echo $one['created_at'].'_===_'.$seconds.'==='."{$flag}|||{$loginTime}";
                    continue;
                }

                if ($flag == 1 && $loginTime != null && $lastTime['act'] == 0) {
//                    print_r($lastTime);
//                    echo $one['created_at'].'_===_'.$seconds.'==='."{$flag}|||{$loginTime}";
                    continue;
                }

                if ($flag == 1 && $loginTime != null && $lastTime['act'] == 1) {
                    $seconds += strtotime($one['created_at']) - strtotime($loginTime);
                    $loginTime = null;
                    $flag = 0;
//                    echo $one['created_at'].'_===_'.$seconds.'==='."{$flag}|||{$loginTime}";
                }

                if ($flag == 1 && !($lastTime)){
                    $seconds += strtotime($one['created_at']) - strtotime($loginTime);
                    $loginTime = null;
                    $flag = 0;
                }
            }
        }

        return $seconds;
    }

    public static function onlineDurationV2($userId = 0, $start = '', $end = '')
    {
        if (!$userId) return [];
        $where = [];
        $start && $where[] = ['created_at', '>=', $start];
        $end && $where[] = ['created_at', '<', $end];
        $field = ['user_id', 'created_at', 'act'];
        if (!is_array($userId)) {
            $userId = [$userId];
        }

//        $data = self::where($where)->whereIn('user_id', $userId)->whereIn('act', [1, 0])->select($field)->orderBy('id', 'asc')->get()->toArray();
        $loginData = self::where($where)->where('act',1)->select($field)->orderBy('id','asc')->get()->toArray();
        $logoutData = self::where($where)->where('act',0)->select($field)->orderBy('id','asc')->get()->toArray();

        $loginClassifiedData = [];
        $logoutClassifiedData = [];

        // 遍历原始数组，根据 'type' 列值归类产品信息
        foreach ($loginData as $item) {
            $type = $item['user_id'];

            // 如果当前类型尚未存在于归类数组中，则初始化一个空数组
            if (!isset($loginClassifiedData[$type])) {
                $loginClassifiedData[$type] = [];
            }

            $loginClassifiedData[$type][] = $item;
        }

        foreach ($logoutData as $item2) {
            $type = $item2['user_id'];

            if (!isset($logoutClassifiedData[$type])) {
                $logoutClassifiedData[$type] = [];
            }

            $logoutClassifiedData[$type][] = $item2;
        }

        $res = [];

        foreach ($userId as $oneUser)
        {
            $loginTimes = array_unique(array_column($loginClassifiedData[$oneUser],'created_at'));
            $logoutTimes = array_unique(array_column($logoutClassifiedData[$oneUser],'created_at'));
            if (empty($loginTimes) && empty($logoutTimes)) {
                $res[$oneUser] = 0;
                continue;
            }

            sort($loginTimes);
            sort($logoutTimes);

            $seconds = 0;

            if(min($logoutTimes) < min($loginTimes)) {
                $seconds += strtotime(min($logoutTimes)) - strtotime($start);
            }

//            var_dump($loginTimes);
            $lastLogoutTime = min($loginTimes);
            $lastSecond = 0;
            foreach ($loginTimes as $loginTime)
            {
//                if ($loginTime == min($loginTimes)) {
//                    continue;
//                }

                $lastLoginTimes = next($loginTimes);
                $filteredNumbers = array_filter($logoutTimes, function($value) use ($lastLoginTimes) {
                    return $value <= $lastLoginTimes;
                });

                if (!empty($filteredNumbers)) {
                    // 使用 max() 函数获取筛选后的数组中的最大值
                    $maxValue = max($filteredNumbers);
//                    echo $maxValue;
//                    echo "\n";;
                    if ($maxValue == $lastLogoutTime) {
                        $seconds -= $lastSecond;
//                        continue;
                    }

                    $seconds += ($lastSecond = strtotime($maxValue) - strtotime($loginTime));
                    $lastLogoutTime = $maxValue;
                } else {
                    $maxEndTimes = max($logoutTimes);
                    if ($loginTime > $maxEndTimes) {
                        if (strtotime($end) - time() < 60) {
                            $maxEndTimes = $end;
                        }else{
                            $maxEndTimes = $loginTime;
                        }
                    }
                    $seconds += strtotime($maxEndTimes) - strtotime($loginTime);
                }

//                echo $loginTime .'+'.$seconds;
//                echo "\n";
            }

            $res[$oneUser] = $seconds;
        }

        return $res;
    }
}